package com.gjy.disruptor.uuid.dec.disruptor;

import com.fasterxml.uuid.Generators;
import com.fasterxml.uuid.impl.RandomBasedGenerator;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import lombok.Getter;
import org.slf4j.Logger;

import java.util.concurrent.Executors;

/**
 * Disruptor事件生产者。
 * 负责初始化Disruptor，并提供一个方法来触发UUID生成事件。
 *
 * @author gjy
 * @version 1.0
 * @since 2025-10-11 09:14:28
 */
public class UuidEventProducer {

    private static final Logger logger = org.slf4j.LoggerFactory.getLogger(UuidEventProducer.class);

    private final RingBuffer<UuidEvent> ringBuffer;
    private final RandomBasedGenerator uuidGenerator;
    private final Disruptor<UuidEvent> disruptor;
    /**
     * -- GETTER --
     * 获取与Disruptor关联的EventHandler，以便Netty可以从中获取UUID。
     */
    @Getter
    private final UuidEventHandler eventHandler; // 直接持有EventHandler引用

    public UuidEventProducer() {
        // 2. 创建事件工厂
        UuidEventFactory factory = new UuidEventFactory();

        // 3. 指定RingBuffer大小，必须是2的幂
        int ringBufferSize = 1024;

        // 4. 构造Disruptor
        this.disruptor = new Disruptor<>(factory, ringBufferSize, Executors.defaultThreadFactory(), ProducerType.SINGLE, new YieldingWaitStrategy());

        // 5. 创建并连接消费者 (EventHandler)
        this.eventHandler = new UuidEventHandler(); // 在构造函数中创建
        disruptor.handleEventsWith(this.eventHandler);

        // 6. 启动Disruptor
        this.ringBuffer = disruptor.start();

        // 7. 初始化UUID生成器
        this.uuidGenerator = Generators.randomBasedGenerator();

        logger.info("Disruptor started with buffer size: {}", ringBufferSize);
    }

    /**
     * 触发一次UUID生成事件。
     * 这个方法会被Netty的请求处理器调用。
     */
    public void produce() {
        // 使用Translator将数据发布到RingBuffer
        ringBuffer.publishEvent(UuidEventTranslator.INSTANCE, uuidGenerator);
    }

    /**
     * 关闭Disruptor和Executor
     */
    public void shutdown() {
        disruptor.shutdown();
        logger.info("Disruptor and ExecutorService shut down.");
    }

}
